import { qdrantClient } from '@/lib/db';
import {
  embeddingModel,
  getOptimizedDeepSeekClient,
  DEEPSEEK_PRESETS,
} from '@/lib/deepseek';
import { ChatMessage } from '@/types';
import { HumanMessage, SystemMessage } from '@langchain/core/messages';

/**
 * 增强的RAG系统
 * 提供智能的文档检索、上下文融合和回答生成
 */
export class EnhancedRAGSystem {
  private collectionName: string;
  private maxDocuments: number;
  private minSimilarity: number;
  private contextFusionThreshold: number;

  constructor(
    options: {
      collectionName?: string;
      maxDocuments?: number;
      minSimilarity?: number;
      contextFusionThreshold?: number;
    } = {}
  ) {
    this.collectionName = options.collectionName || 'documents';
    this.maxDocuments = options.maxDocuments || 8;
    this.minSimilarity = options.minSimilarity || 0.7;
    this.contextFusionThreshold = options.contextFusionThreshold || 0.8;
  }

  /**
   * 智能文档检索
   * @param query 查询文本
   * @param conversationHistory 对话历史
   * @param userId 用户ID
   * @returns 检索结果
   */
  async intelligentRetrieval(
    query: string,
    conversationHistory: ChatMessage[] = [],
    userId?: string
  ): Promise<{
    results: any[];
    expandedQuery: string;
    retrievalStrategy: string;
    confidence: number;
  }> {
    // 1. 查询扩展
    const expandedQuery = await this.expandQuery(query, conversationHistory);

    // 2. 多策略检索
    const strategies = await Promise.all([
      this.vectorSearch(expandedQuery, userId),
      this.semanticSearch(query, userId),
      this.contextualSearch(query, conversationHistory, userId),
    ]);

    // 3. 结果融合
    const fusedResults = this.fuseResults(strategies);

    // 4. 智能排序
    const rankedResults = this.intelligentRanking(
      fusedResults,
      query,
      conversationHistory
    );

    // 5. 计算检索置信度
    const confidence = this.calculateRetrievalConfidence(rankedResults);

    return {
      results: rankedResults.slice(0, this.maxDocuments),
      expandedQuery,
      retrievalStrategy: 'multi_strategy_fusion',
      confidence,
    };
  }

  /**
   * 查询扩展
   */
  private async expandQuery(
    query: string,
    history: ChatMessage[]
  ): Promise<string> {
    if (history.length === 0) return query;

    // 获取最近的对话上下文
    const recentContext = history
      .slice(-4)
      .map(msg => `${msg.role}: ${msg.content}`)
      .join('\n');

    const expansionPrompt = `基于以下对话历史，扩展用户的查询以获得更好的搜索结果：

对话历史：
${recentContext}

当前查询：${query}

请生成一个扩展的搜索查询，包含相关的关键词和概念，但保持简洁：`;

    try {
      const client = getOptimizedDeepSeekClient('analytical');
      const response = await client.invoke([
        new SystemMessage(
          '你是一个专业的查询扩展助手，能够基于对话上下文生成更好的搜索查询。'
        ),
        new HumanMessage(expansionPrompt),
      ]);

      const expandedQuery = response.content as string;
      return expandedQuery.trim() || query;
    } catch (error) {
      console.error('查询扩展失败:', error);
      return query;
    }
  }

  /**
   * 向量搜索
   */
  private async vectorSearch(query: string, userId?: string): Promise<any[]> {
    try {
      const queryEmbedding = await embeddingModel.embedQuery(query);

      const filter = userId ? { user_id: userId } : undefined;

      const searchResult = await qdrantClient.search(this.collectionName, {
        vector: queryEmbedding,
        limit: this.maxDocuments * 2,
        score_threshold: this.minSimilarity,
        filter,
      });

      return searchResult.map(result => ({
        ...result.payload,
        score: result.score,
        strategy: 'vector',
      }));
    } catch (error) {
      console.error('向量搜索失败:', error);
      return [];
    }
  }

  /**
   * 语义搜索
   */
  private async semanticSearch(query: string, userId?: string): Promise<any[]> {
    try {
      // 使用不同的嵌入策略
      const semanticQuery = await this.generateSemanticQuery(query);
      const queryEmbedding = await embeddingModel.embedQuery(semanticQuery);

      const filter = userId ? { user_id: userId } : undefined;

      const searchResult = await qdrantClient.search(this.collectionName, {
        vector: queryEmbedding,
        limit: this.maxDocuments,
        score_threshold: this.minSimilarity * 0.9,
        filter,
      });

      return searchResult.map(result => ({
        ...result.payload,
        score: result.score * 0.95, // 略微降低语义搜索的权重
        strategy: 'semantic',
      }));
    } catch (error) {
      console.error('语义搜索失败:', error);
      return [];
    }
  }

  /**
   * 上下文搜索
   */
  private async contextualSearch(
    query: string,
    history: ChatMessage[],
    userId?: string
  ): Promise<any[]> {
    if (history.length === 0) return [];

    try {
      // 构建上下文查询
      const contextQuery = this.buildContextualQuery(query, history);
      const queryEmbedding = await embeddingModel.embedQuery(contextQuery);

      const filter = userId ? { user_id: userId } : undefined;

      const searchResult = await qdrantClient.search(this.collectionName, {
        vector: queryEmbedding,
        limit: this.maxDocuments,
        score_threshold: this.minSimilarity * 0.8,
        filter,
      });

      return searchResult.map(result => ({
        ...result.payload,
        score: result.score * 0.9,
        strategy: 'contextual',
      }));
    } catch (error) {
      console.error('上下文搜索失败:', error);
      return [];
    }
  }

  /**
   * 生成语义查询
   */
  private async generateSemanticQuery(query: string): Promise<string> {
    // 简单的语义扩展逻辑
    const synonyms: Record<string, string[]> = {
      问题: ['疑问', '困惑', '难题'],
      方法: ['方式', '途径', '手段'],
      解决: ['处理', '应对', '解答'],
      如何: ['怎样', '怎么', '如何才能'],
    };

    let semanticQuery = query;

    for (const [word, syns] of Object.entries(synonyms)) {
      if (query.includes(word)) {
        semanticQuery += ' ' + syns.join(' ');
      }
    }

    return semanticQuery;
  }

  /**
   * 构建上下文查询
   */
  private buildContextualQuery(query: string, history: ChatMessage[]): string {
    const recentMessages = history.slice(-3);
    const contextKeywords = recentMessages
      .map(msg => this.extractKeywords(msg.content))
      .flat()
      .slice(0, 5);

    return `${query} ${contextKeywords.join(' ')}`;
  }

  /**
   * 提取关键词
   */
  private extractKeywords(text: string): string[] {
    // 简单的关键词提取
    const words = text.match(/[\u4e00-\u9fa5a-zA-Z]{2,}/g) || [];
    const stopWords = [
      '什么',
      '如何',
      '怎么',
      '为什么',
      '可以',
      '能否',
      '请问',
      '这个',
      '那个',
    ];

    return words
      .filter(word => !stopWords.includes(word) && word.length > 1)
      .slice(0, 3);
  }

  /**
   * 结果融合
   */
  private fuseResults(strategies: any[][]): any[] {
    const allResults = strategies.flat();
    const resultMap = new Map<string, any>();

    // 合并相同文档的结果
    for (const result of allResults) {
      const key = result.id || result.title;
      if (resultMap.has(key)) {
        const existing = resultMap.get(key)!;
        // 使用最高分数，并记录多个策略
        existing.score = Math.max(existing.score, result.score);
        existing.strategies = [
          ...(existing.strategies || [existing.strategy]),
          result.strategy,
        ];
        existing.strategyCount = existing.strategies.length;
      } else {
        resultMap.set(key, {
          ...result,
          strategies: [result.strategy],
          strategyCount: 1,
        });
      }
    }

    return Array.from(resultMap.values());
  }

  /**
   * 智能排序
   */
  private intelligentRanking(
    results: any[],
    query: string,
    history: ChatMessage[]
  ): any[] {
    return results.sort((a, b) => {
      // 1. 基础分数权重 (40%)
      const scoreA = a.score * 0.4;
      const scoreB = b.score * 0.4;

      // 2. 策略多样性权重 (20%)
      const diversityA = (a.strategyCount || 1) * 0.2;
      const diversityB = (b.strategyCount || 1) * 0.2;

      // 3. 文档新鲜度权重 (20%)
      const freshnessA = this.calculateFreshness(a) * 0.2;
      const freshnessB = this.calculateFreshness(b) * 0.2;

      // 4. 查询相关性权重 (20%)
      const relevanceA = this.calculateQueryRelevance(a, query) * 0.2;
      const relevanceB = this.calculateQueryRelevance(b, query) * 0.2;

      const totalA = scoreA + diversityA + freshnessA + relevanceA;
      const totalB = scoreB + diversityB + freshnessB + relevanceB;

      return totalB - totalA;
    });
  }

  /**
   * 计算文档新鲜度
   */
  private calculateFreshness(result: any): number {
    if (!result.created_at) return 0.5;

    const now = Date.now();
    const created = new Date(result.created_at).getTime();
    const daysDiff = (now - created) / (1000 * 60 * 60 * 24);

    // 30天内的文档得分较高
    if (daysDiff <= 30) return 1.0;
    if (daysDiff <= 90) return 0.8;
    if (daysDiff <= 180) return 0.6;
    return 0.4;
  }

  /**
   * 计算查询相关性
   */
  private calculateQueryRelevance(result: any, query: string): number {
    const title = (result.title || '').toLowerCase();
    const content = (result.content || '').toLowerCase();
    const queryLower = query.toLowerCase();

    let relevance = 0;

    // 标题匹配
    if (title.includes(queryLower)) relevance += 0.5;

    // 内容匹配
    const queryWords = queryLower.split(/\s+/);
    const matchCount = queryWords.filter(
      word => title.includes(word) || content.includes(word)
    ).length;

    relevance += (matchCount / queryWords.length) * 0.5;

    return Math.min(relevance, 1.0);
  }

  /**
   * 计算检索置信度
   */
  private calculateRetrievalConfidence(results: any[]): number {
    if (results.length === 0) return 0;

    const avgScore =
      results.reduce((sum, r) => sum + r.score, 0) / results.length;
    const topScore = results[0]?.score || 0;
    const resultCount = Math.min(results.length, this.maxDocuments);

    // 综合考虑平均分数、最高分数和结果数量
    const confidence =
      avgScore * 0.4 + topScore * 0.4 + (resultCount / this.maxDocuments) * 0.2;

    return Math.min(confidence, 1.0);
  }

  /**
   * 生成增强的RAG响应
   */
  async generateEnhancedResponse(
    query: string,
    retrievalResult: any,
    conversationHistory: ChatMessage[] = []
  ): Promise<{
    response: string;
    confidence: number;
    sources: any[];
    reasoning: string;
  }> {
    const { results, confidence, expandedQuery } = retrievalResult;

    if (results.length === 0) {
      return {
        response:
          '抱歉，我没有找到相关的文档信息来回答您的问题。请尝试重新表述您的问题或提供更多上下文。',
        confidence: 0,
        sources: [],
        reasoning: '未找到相关文档',
      };
    }

    // 构建增强的上下文
    const enhancedContext = this.buildEnhancedContext(
      results,
      query,
      expandedQuery
    );

    // 选择合适的模型配置
    const modelConfig = confidence > 0.8 ? 'rag' : 'analytical';
    const client = getOptimizedDeepSeekClient(modelConfig);

    // 构建系统提示
    const systemPrompt = this.buildEnhancedSystemPrompt(
      confidence,
      results.length
    );

    // 构建用户提示
    const userPrompt = `基于以下文档信息回答问题：

${enhancedContext}

问题：${query}

请提供准确、有帮助的回答，并在适当时引用相关文档。`;

    try {
      const response = await client.invoke([
        new SystemMessage(systemPrompt),
        new HumanMessage(userPrompt),
      ]);

      return {
        response: response.content as string,
        confidence,
        sources: results.slice(0, 3),
        reasoning: `基于${results.length}个相关文档，检索置信度${(confidence * 100).toFixed(1)}%`,
      };
    } catch (error) {
      console.error('生成RAG响应失败:', error);
      return {
        response: '抱歉，生成回答时出现错误，请稍后重试。',
        confidence: 0,
        sources: [],
        reasoning: '生成失败',
      };
    }
  }

  /**
   * 构建增强的上下文
   */
  private buildEnhancedContext(
    results: any[],
    originalQuery: string,
    expandedQuery: string
  ): string {
    let context = '';

    // 添加查询信息
    if (expandedQuery !== originalQuery) {
      context += `扩展查询：${expandedQuery}\n\n`;
    }

    // 添加文档信息
    results.forEach((result, index) => {
      context += `[文档${index + 1}] ${result.title}\n`;
      context += `相似度：${(result.score * 100).toFixed(1)}%\n`;
      context += `内容：${result.content}\n`;

      if (result.metadata) {
        context += `元数据：${JSON.stringify(result.metadata)}\n`;
      }

      context += '\n---\n\n';
    });

    return context;
  }

  /**
   * 构建增强的系统提示
   */
  private buildEnhancedSystemPrompt(
    confidence: number,
    resultCount: number
  ): string {
    let prompt = `你是一个专业的AI助手，擅长基于文档内容提供准确、有帮助的回答。

当前检索情况：
- 检索置信度：${(confidence * 100).toFixed(1)}%
- 相关文档数量：${resultCount}个

请遵循以下原则：
1. 优先基于提供的文档内容回答问题
2. 保持回答的准确性和相关性
3. 适当引用文档来源
4. 如果文档信息不足，请明确说明
5. 提供结构化、易理解的回答`;

    if (confidence < 0.5) {
      prompt += `\n\n⚠️ 注意：当前检索置信度较低，请谨慎回答，并建议用户提供更多信息。`;
    } else if (confidence > 0.8) {
      prompt += `\n\n✅ 检索质量良好，可以提供详细、准确的回答。`;
    }

    return prompt;
  }
}

// 导出单例实例
export const enhancedRAG = new EnhancedRAGSystem();
